import { reactive } from "vue";
import { Num, U16, U32, U8 } from "./codec";
import { Message } from "./message";
import { hex4 } from "./ui";

export class Max311855 {

    d_31_18: number;
    d16: boolean; // FAULT
    d_15_4: number;

    d2: boolean; // SCV
    d1: boolean; // SCG
    d0: boolean; // OC

    thermocouple_temp: number;
    junction_temp: number;

    constructor(value: U32) {
        this.d_31_18 = value.value >> 18;
        this.d16 = value.isBitSet(16);
        this.d_15_4 = (value.value >> 4) & 0xFFF;
        this.d2 = value.isBitSet(2);
        this.d1 = value.isBitSet(1);
        this.d0 = value.isBitSet(0);

        if (0x00 != (this.d_31_18 & 0x2000)) {
            this.thermocouple_temp = -(0x4000 - this.d_31_18) * 0.25;
        } else {
            this.thermocouple_temp = this.d_31_18 * 0.25;
        }

        if (0x00 != (this.d_15_4 & 0x800)) {
            this.junction_temp = (0x1000 - this.d_15_4) * 0.0625;
        } else {
            this.junction_temp = this.d_15_4 * 0.0625;
        }
    }

}

export class HeatSwSensor {
    leak: boolean;
    
    tank2_low: boolean;
    tank2_sw: boolean;
    
    tank1_low: boolean;
    tank1_sw: boolean;

    reserve_low: boolean;
    reserve_sv1: boolean;
    reserve_sv2: boolean;
    reserve_sv3: boolean;

    nozzle_alm: boolean;
    nozzle_origin: boolean;
    nozzle_origin2: boolean;
    front_bucket_fail: boolean;
    back_bucket_fail: boolean;

    constructor(v: U16) {
        this.leak = v.isBitSet(0);
        this.tank2_low = v.isBitSet(1);
        this.tank2_sw = v.isBitSet(2);
        this.tank1_low = v.isBitSet(3);
        this.tank1_sw = v.isBitSet(4);
        this.reserve_low = v.isBitSet(5);
        this.reserve_sv1 = v.isBitSet(6);
        this.reserve_sv2 = v.isBitSet(7);
        this.reserve_sv3 = v.isBitSet(8);
        this.nozzle_alm = v.isBitSet(9);
        this.nozzle_origin = v.isBitSet(10);
        this.nozzle_origin2 = v.isBitSet(11);
        this.front_bucket_fail = v.isBitSet(12);
        this.back_bucket_fail = v.isBitSet(13);
    }
}

export class HeatCtrl {
    reserve_heat: boolean;
    tank1_heat: boolean;
    tank2_heat: boolean;
    v1: boolean;
    v2: boolean;
    v3: boolean;
    v4: boolean;
    v5: boolean;
    v6: boolean;
    v7: boolean;
    v8: boolean;
    v9: boolean;
    v10: boolean;
    p1: boolean;
    p2: boolean;
    p3: boolean;

    constructor(v: U16) {
        this.reserve_heat = v.isBitSet(0);
        this.tank1_heat = v.isBitSet(1);
        this.tank2_heat = v.isBitSet(2);
        this.v1 = v.isBitSet(3);
        this.v2 = v.isBitSet(4);
        this.v3 = v.isBitSet(5);
        this.v4 = v.isBitSet(6);
        this.v5 = v.isBitSet(7);
        this.v6 = v.isBitSet(8);
        this.v7 = v.isBitSet(9);
        this.v8 = v.isBitSet(10);
        this.v9 = v.isBitSet(11);
        this.v10 = v.isBitSet(12);
        this.p1 = v.isBitSet(13);
        this.p2 = v.isBitSet(14);
        this.p3 = v.isBitSet(15);
    }
}

export interface HeatState {
    version: string,
    
    reserve_max31855: Max311855,
    tank1_max31855: Max311855,
    tank2_max31855: Max311855,

    reserve_temp: number,
    tank1_temp: number,
    tank2_temp: number,

    tank1_kpa: number,
    tank2_kpa: number,

    flow_count: number,
    sw: HeatSwSensor,
    ctrl: HeatCtrl,
    draw_reserve_info: string,
    draw_tank_info: string,
    heat_info: string,
}

export const heatState = reactive<HeatState>({
    version: '',

    reserve_max31855: new Max311855( new U32 ),
    tank1_max31855: new Max311855( new U32 ),
    tank2_max31855: new Max311855( new U32 ),

    reserve_temp: 0,
    tank1_temp: 0,
    tank2_temp: 0,
    tank1_kpa: 0,
    tank2_kpa: 0,
    flow_count: 0,
    sw: new HeatSwSensor(new U16),
    ctrl: new HeatCtrl(new U16),
    draw_reserve_info: '未知',
    draw_tank_info: '未知',
    heat_info: '未知',
});

function drawReserveInfo(val: number) {
    switch (val) {
        case 0: return '空闲';
        case 1: return '低水位不足抽水';
        case 2: return 'SV1不足抽水';
        case 3: return 'SV2不足抽水';
        case 4: return 'SV3不足抽水';
        case 5: return '故障/缺水';
        case 6: return '停机';
        case 7: return '超时';
        default: return '未知情况';
    }
}

function drawTankInfo(val: number) {
    switch (val) {
        case 0: return '空闲';
        case 1: return '停机';
        case 2: return '抽加热罐1';
        case 3: return '抽加热罐2';
        case 4: return '抽加热罐1超时';
        case 5: return '抽加热罐2超时';
        default: return '未知情况';
    }
}

function heatInfo(val: number) {
    switch (val) {
        case 0: return '保温';
        case 1: return '停机';
        case 2: return '故障';
        case 3: return '蓄热罐加热超时';
        case 4: return '加热罐1加热超时';
        case 5: return '加热罐2加热超时';
        default: return '未知情况';
    }
}

export function onHeatStatus(msg: Message) {
    
    const verson = new U16();
    const reserve_max31855 = new U32();
    const tank1_max31855 = new U32();
    const tank2_max31855 = new U32();
    const reserve_temp = new U16();
    const tank1_temp = new U16();
    const tank2_temp = new U16();
    const tank1_kpa = new U16();
    const tank2_kpa = new U16();
    const flow_count = new U16();
    const sw = new U16();
    const ctrl = new U16();
    const reserve_info = new U8();
    const tank_info = new U8();
    const heat_info = new U8();

    msg.parseResult(
        verson, 
        reserve_max31855, tank1_max31855, tank2_max31855,
        reserve_temp, tank1_temp, tank2_temp,
        tank1_kpa, tank2_kpa,
        flow_count,
        sw,
        ctrl,
        reserve_info, tank_info, heat_info
    );
  
    heatState.version = hex4(verson.value);
    heatState.reserve_max31855 = new Max311855( reserve_max31855 );
    heatState.tank1_max31855 = new Max311855( tank1_max31855 );
    heatState.tank2_max31855 = new Max311855( tank2_max31855 );
    heatState.reserve_temp = reserve_temp.signedValue();
    heatState.tank1_temp = tank1_temp.signedValue();
    heatState.tank2_temp = tank2_temp.signedValue();
    heatState.tank1_kpa = tank1_kpa.value;
    heatState.tank2_kpa = tank2_kpa.value;
    heatState.flow_count = flow_count.value;
    heatState.sw = new HeatSwSensor( sw );
    heatState.ctrl = new HeatCtrl( ctrl );

    heatState.draw_reserve_info = drawReserveInfo(reserve_info.value);
    heatState.draw_tank_info = drawTankInfo(tank_info.value);
    heatState.heat_info = heatInfo(heat_info.value);
}
